import javax.microedition.lcdui.Canvas;
import javax.microedition.lcdui.Image;
import javax.microedition.media.Player;
import javax.microedition.media.Manager;
import java.io.InputStream;
import java.lang.Object;
import java.io.IOException;
import java.util.Random;
import javax.microedition.rms.*;
import javax.microedition.lcdui.Graphics;
import javax.microedition.lcdui.game.Sprite;
import javax.wireless.messaging.MessageConnection;
import javax.wireless.messaging.TextMessage;
import javax.microedition.io.ConnectionNotFoundException;
import javax.microedition.io.Connector;

#include "defines.h"

class cGame extends Canvas implements Runnable
{
	//------------------------------------//
	public static int keyflags;
	public static CABJMID midlet_instance;
	public static Thread t;
	public static boolean started;
	public static DGraph cGame_g;
	public static EMidFont fonts;
	public static String error;
	public static int fps;
	
	// Resources variables.
	public static Image [] shields;
	public static Image logo;
	public static Image logo_o;
	public static Image logo_pel;
	public static Image arrow;
	public static Image arrowSelected;
	public static Image okBut;
	public static Image okButSelected;
	
	// Connection variables.
	public static boolean isSMSSent = false;
	public static String debugServerNumber = null;
	
	public static String currInputText = null;
	
	// States variables
	public static int game_state;
	public static int prev_game_state;
	public static int subState = 0;
	
	// Screen Dimension variables.
	public static final int[] SCR_WIDTH = {0};
	public static final int[] SCR_HEIGHT = {0};
	public static int SCREEN_MIN_EDGE;
	public static int sKMarginFromEdge;
	// Used to fit the resources according to the default resolution. This helps to make the app more resizable.
	public static int proportional;

	// Is the offset used to simulate the movement of an item.
	public static int movementOffset;
	// The value that the offset is modified in each loop.
	public static final int MOVEMENT_OFFSET = 1;
	// The maximum value that the offset can reach.
	public static final int MOVEMENT_MAX_OFFSET = 3;
	// The minimum offset.
	public static final int MOVEMENT_NULL_OFFSET = 0;
	// To know if the offset must be increased or decreased.
	public static boolean incOffset = true;
	// To know if it is necesary to set the keys or not.
	public static boolean needToSetKeys = false;
	// To know if it is necesary to set the keys or not.
	public static boolean needToRepaint = true;
	
	/* DIDI MESSAGE: implement another way to know if a team has been selected */
	/* THIS WILL BE DELETED - DO NOT USE teamName */
	// The name of the team that has been selected.
	public static String teamName;
	/* DIDI MESSAGE END */
	
	// General color variables.
	public static int alphaBackcolor = 0x77ffffff; // TODO: traelo de lo exportado por DIDI. Aca iria la general, se puede overraidear en cada pantalla particular.
	public static int logoAlphaColor = 0xffffffff; // TODO: traelo de lo exportado por DIDI. Aca iria la general, se puede overraidear en cada pantalla particular.
	public static int backgroundColor = 0x333333; // TODO: traelo de lo exportado por DIDI. Aca iria la general, se puede overraidear en cada pantalla particular.
	
	// General spacing variables.
	public static int lineSpacing;	// TODO: traelo de lo exportado por DIDI. Se exmpresa en proporcion a la pantalla.
	public static int titleY;		// TODO: traelo de lo exportado por DIDI. Se exmpresa en proporcion a la pantalla.
	
	// Offsets to find the values in the KEYS_TO_DRAW matrix.
	public static final byte X 	= 0;
	public static final byte Y 	= 1;
	public static final byte W 	= 2;
	public static final byte H 	= 3;
	
	public static void setState(int new_state)
	{
		load(new_state);
		prev_game_state = game_state;
		game_state = new_state;
		subState = STATES.INIT;
	}

	public static void setState(int new_state, int sub_state)
	{
		load(new_state);
		prev_game_state = game_state;
		game_state = new_state;
		subState = sub_state;
	}
	
	#ifdef TOUCH_SCREEN
		#include "TouchScreen.h"
	#endif

	public cGame()
	{
	}

	public cGame(CABJMID _mid)
	{
		midlet_instance = _mid;
		setFullScreenMode(true);
		t = new Thread(this);
		if (loadKeysSettings() == null) 
		{
			needToSetKeys = true;
		}
		loadTeamName();
		setState(STATES.AUTO_SETTINGS);
	}

	#include "cGame_AutoSettings.h"
	#include "cGame_Intro.h"
	#include "cGame_Loading.h"
	#include "cGame_SetKeys.java"
	#include "cGame_TeamSelection.h"
	#include "cGame_Error.h"
	#include "cGame_TemplateHandler.h"
	#include "cGame_RMS.h"
	
	protected void paint(javax.microedition.lcdui.Graphics g)
	{
		if(cGame_g == null)
		{
			initGeneralValues();
			SCREEN_MIN_EDGE = SCREEN_HEIGHT > SCREEN_WIDTH ? SCREEN_WIDTH : SCREEN_HEIGHT;
			
			#ifdef USE_BACK_BUFFER
				cGame_g = new DGraph(g, SCREEN_WIDTH, SCREEN_HEIGHT, true);
			#else
				cGame_g = new DGraph(g, SCREEN_WIDTH, SCREEN_HEIGHT, false);
			#endif
		
			fonts = new EMidFont(g, SCREEN_HEIGHT);
		}			
		
		#ifdef USE_BACK_BUFFER
		cGame_g.paintBuffer();
		#endif
		
		g = cGame_g.getFgGraphics();
		
		switch(game_state)
		{
			case STATES.AUTO_SETTINGS:
				autoSettings();
			break;
			
			#ifdef HAS_INTRO
			case STATES.INTRO:
				updateIntro();
			break;
			#endif
			
			#ifdef HAS_SET_KEYS
			case STATES.SET_KEYS:
				if (needToSetKeys) 
				{
					updateSetKeys();
				} 
				else
				{
				#ifdef HAS_TEAM_SELECTION
					setState(STATES.TEAM_SELECTION);
				#else
					setState(STATES.TEMPLATE_HANDLER);
				#endif
				}
			break;
			#endif
			
			#ifdef HAS_TEAM_SELECTION
			case STATES.TEAM_SELECTION:
				/* DIDI MESSAGE: implement another way to know if a team has been selected */
				/* THIS WILL BE DELETED - DO NOT USE teamName */
				if (teamName == null)
				/* DIDI MESSAGE END */
				{
					updateTeamSelection();
				}
				else
				{
					setState(STATES.TEMPLATE_HANDLER);
				}
				break;
			#endif
			
			case STATES.TEMPLATE_HANDLER:
				updateTemplateHandler();
//				g.drawString("" + isSMSSent, 50, 100, DSmallFont.BOTTOM | DSmallFont.HCENTER); //JMZY
			break;
		}
		newEvent = false;
		
		clearAction(false);
	}
	
	boolean read = false;

	protected void hideNotify()
	{
	}

	protected void showNotify()
	{
	}

	#include "KEYEVENTS.H"
	
	/**
	 * Loop principal de la aplicacion.
	 * */
	public void run()
	{
		started = true;
		
		while(started)
		{
			if (fps >= INTERFACE.MAX_FPS)
			{
				repaint();
				fps = 0;
			} 
			else
			{
				fps++;
				try
				{
					Thread.sleep(INTERFACE.THREAD_SLEEP);
				}
				catch(Exception e)
				{
				}
			}
			if (error != null) 
			{
//				setState(STATES.ERROR); //TODO: Lo comento por ahora porq no quiero perder tiempo en esto. La idea es avisarle al usario q ocurrio un error y para eso uso un estado.
				DEB_OUT(error);
				rmsSave(RMS_INFO.APP_LAST_ERROR, error.getBytes());
				error = null;
			}
		}
		midlet_instance.notifyDestroyed();
	}

	/**
	 * Updates the offset used to simulate the movement of the items in the screen.
	 * */
	static void updateMovementOffset()
	{
		if (incOffset) 
		{
			movementOffset += MOVEMENT_OFFSET;
			if (movementOffset >= MOVEMENT_MAX_OFFSET) 
			{
				incOffset = false;
			}
		} 
		else
		{
			movementOffset -= MOVEMENT_OFFSET;
			if (movementOffset <= MOVEMENT_NULL_OFFSET) 
			{
				incOffset = true;
			}
		}
	}
	
	/**
	 * Loads the key setting saved by the user.
	 * */
	public byte [] loadKeysSettings()
	{
		byte [] keySetLoaded = rmsLoad(RMS_INFO.KEY_SET);
		String keysString;
		if (keySetLoaded  != null) 
		{
			keysString = new String (keySetLoaded);
			String [] aux = EMidFont.split(keysString, ",");
			for (int i = 0 ; i < aux.length ; ++i)
			{
				KEYS.SET[i] = Integer.parseInt(aux[i]);
				System.out.println("KEYS.SET[" + i + "]: " + KEYS.SET[i]);
			}
		}
		return keySetLoaded;
	}
	
	/* DIDI MESSAGE: implement another way to know if a team has been selected */
	/* THIS WILL BE DELETED - DO NOT USE teamName */
	/**
	 * Carga el nombre del equipo elegido.
	 * */
	public byte [] loadTeamName()
	{
		byte [] teamNamedata = rmsLoad(RMS_INFO.TEAM_SELECTED);
		if (teamNamedata != null)
		{
			teamName = new String (teamNamedata);
		}
		DEB_OUT("Team Name: " + teamName);
		return teamNamedata;
	}
	/* DIDI MESSAGE END */
}

